package com.weixin.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class AnalyzeXmlUtil {
	/**
	 * 获取request中的xml流，将其转化为xml节点对象
	 * 
	 * @param request
	 */
	public static Document getDocument(HttpServletRequest request) {
		SAXReader reader = new SAXReader();
		Document document = null;
		InputStream in = null;
		try {
			in = request.getInputStream();
			document = reader.read(in);
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (document != null) {
			return document;
		}
		return null;
	}

	/**
	 * 将document对象转化为实体类对象
	 * 
	 * @param document
	 * @param obj
	 */
	public static Object getObject(Document document, Object obj) {
		Element root = document.getRootElement();
		List<Element> elements = root.elements();
		Class clazz = obj.getClass();
		for (int i = 0; i < elements.size(); i++) {
			Element element = elements.get(i);
			try {
				PropertyDescriptor pd = new PropertyDescriptor(element.getName(), clazz);
				Method method = pd.getWriteMethod();
				method.invoke(obj, element.getText());
			} catch (Exception e) {
				System.out.println("执行失败");
				System.out.println("异常:" + e);
			}
		}
		return obj;
	}

	/**
	 * 将JavaBean属性数据对象转化为map集合
	 * 
	 * @param JavaBean
	 *            需要转化为Map集合的实体类
	 */
	public static Map<String, Object> getMapByObject(Object JavaBean) {
		Map<String, Object> data = new HashMap<String, Object>();
		Class clazz = JavaBean.getClass();
		// 获取类名
		data.put("className", clazz.getName());
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			String paramMeterName = field.getName();
			try {
				PropertyDescriptor pd = new PropertyDescriptor(paramMeterName, clazz);
				Object paramMeterValue = pd.getReadMethod().invoke(JavaBean, null);
				data.put(paramMeterName, paramMeterValue);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return data;
	}

	/**
	 * 将对象转化为xml流
	 * 
	 * @param obj
	 *            需要转化为xml字符串的对象
	 */
	public static String getXMLByObject(Object obj) {
		StringBuffer xml = new StringBuffer();
		xml.append("<xml>");
		Class clazz = obj.getClass();
		String className=clazz.getName();
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			String fieldName=field.getName();
			xml.append("<" + fieldName + ">");
			try {
				PropertyDescriptor pd = new PropertyDescriptor(fieldName, clazz);
				Object paramMeterValue = pd.getReadMethod().invoke(obj, null);
				if (paramMeterValue == null)
					paramMeterValue = "";
				xml.append(paramMeterValue).append("</" + fieldName + ">");
			} catch (Exception e) {
				System.out.println("反射调用get方法失败");
				System.out.println(e);
			}
		}
		xml.append("</xml>");
		return xml.toString();
	}

	/**
	 * 获取xml中根据节点名获取该节点的文本值
	 * 
	 * @param document
	 *            需要进行查找节点值的document
	 * @param elementName
	 *            节点名
	 */
	public static String getTextByName(Document document, String elementName) {
		Element root = document.getRootElement();
		if (root.element(elementName) != null) {
			return root.elementText(elementName);
		}
		return null;
	}

	/**
	 * 按照map中的key:value来对应节点中的<key>value</key>，如果存在这些个节点则删除，不存在则添加。
	 * 
	 * @param document
	 *            需要进行添加或删除节点的document对象
	 * @param attrs
	 *            需要进行匹配的属性名和属性值
	 * 
	 */
	public static boolean changeElement(Document document, Map<String, Object> attrs) {
		Element root = document.getRootElement();
		Set<Entry<String, Object>> set = attrs.entrySet();
		Iterator<Entry<String, Object>> it = set.iterator();
		// 对attrs中的属性名-属性值进行遍历，一一核对。
		while (it.hasNext()) {
			Entry<String, Object> entry = (Entry<String, Object>) it.next();
			String attrName = entry.getKey().toString();
			if (root.element(attrName) == null)
				root = root.addElement(attrName).addText(entry.getValue().toString());
			else
				root.remove(root.element(attrName));
		}
		return true;
	}

	/**
	 * 根据某个节点属性值来获取该Element对象
	 * 
	 * @param document
	 *            需要进行查找的document对象
	 * @param attrs
	 *            查询条件 key-value 对应 属性名-属性值
	 * 
	 */
	public static Element getElementByAttr(Document document, Map<String, Object> attrs) {
		Element root = document.getRootElement();
		List<Element> elementList = root.elements();
		int index = 0;
		for (int i = 0; i < elementList.size(); i++) {
			Element element = elementList.get(i);
			Set<Entry<String, Object>> set = attrs.entrySet();
			Iterator<Entry<String, Object>> it = set.iterator();
			// 对attrs中的属性名-属性值进行遍历，一一核对。
			while (it.hasNext()) {
				Entry<String, Object> entry = (Entry<String, Object>) it.next();
				String attrName = entry.getKey().toString();
				if (element.attribute(attrName) == null && entry.getValue() == null) {
					index++;
				}
				if (element.attribute(attrName) != null) {
					if (element.attribute(attrName).getValue().equals(entry.getValue())) {
						// 打印信息
						
						index++;
					}
				}
			}
			// 遍历完毕，而且全部满足条件的element
			if (index == attrs.size()) {
				return element;
			}
			index=0;
		}
		return null;
	}

	/**
	 * 将对象转化为document
	 * @param path 保存的路径
	 * @param obj
	 *            需要转化为document的JavaBean对象
	 */
	public static Document getDocumentByObj(Object obj,String path) {
		File file = new File(path,"obj.txt");
		try {
			if (!file.exists()) {
				file.createNewFile();
			}
			file.createNewFile();
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
			BufferedWriter bw = new BufferedWriter(osw);
			String str = getXMLByObject(obj);
//			System.out.println("一调用" + str);测试
			bw.write(str);
			bw.flush();
			bw.close();
			osw.close();
			SAXReader sr = new SAXReader();
			return sr.read(new FileInputStream(file));
		} catch (Exception e) {
			System.out.println(e);
			return null;
		}
	}
}